﻿using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Data.Objects;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Web.UI;
using BusinessApplication.Web.MainEntities;

namespace BusinessApplication1.Web.Services
{
    [ServiceContract(Namespace = "")]
    [SilverlightFaultBehavior]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class ProjectDatabaseInteraction
    {

        [OperationContract]
        public void ImportGeneratedClasses(Project proj, Status stat, Task task, SystemUser user, Notification notific, MsgUserTask mut, PositionDuty posDuty,
            Priority prio, Relations rel, Role rol, Position pos, Execute exec, ReportsTo repTo, Lead lead, ProjectHasStatu prjhastat, TaskHasStatu taskhasstatu, ConnectedWith connwith, TaskProjectStatuses tps)
        {
        }

        [OperationContract]
        public void AddNewRecord()
        {
            // Добавить запись в таблицу Inventory базы данных AutoLot.
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    // Жестко закодировать данные новой записи (для целей тестирования).

                    context.Status.AddObject(new Status { statusName = "Новый статус" });
                    context.SaveChanges();
                }
                catch (Exception ex)
                {

                }
            }
        }
        [OperationContract]
        public void EditStatus(int id)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {

                    context.Status.FirstOrDefault(x => (x.IDStatus == id)).statusName = "Изменил, хахахаха!";
                    context.SaveChanges();
                }
                catch (Exception ex)
                {

                }
            }
        }


            // метод стал ненужен
        [OperationContract]
        public string PrintAllUsers()
        {
             //Выбрать все элементы из таблицы Inventory базы AutoLot и вывести данные,
             //используя специальный метод ToStringO сущностного класса Саг.
            string result = string.Empty;
            using (K223DBEntities context = new K223DBEntities())
            {
                context.Refresh(RefreshMode.StoreWins, context.Status);
                foreach (Status s in context.Status)
                    result += String.Format("StatusId = {0}, StatusName = {1} \n ", s.IDStatus, s.statusName);
            }

            return result;
        }


        [OperationContract]
        public Project AddNewProject(Project projectToAdd)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    Project tempProj = new Project
                    {
                        Description = projectToAdd.Description,
                        Name = projectToAdd.Name,
                        Priority = projectToAdd.Priority,
                        PlanFinishDateTime = projectToAdd.PlanFinishDateTime,
                        PlanStartDateTime = projectToAdd.PlanStartDateTime                    
                    };

                    context.Projects.AddObject(tempProj); 
                    context.SaveChanges();

                    return new Project
                    {
                        IDProject = tempProj.IDProject,
                        Description = tempProj.Description,
                        Name = tempProj.Name,
                        Priority = tempProj.Priority,
                        FactFinishDateTime = tempProj.FactFinishDateTime,
                        FactStartDateTime = tempProj.FactStartDateTime,
                        PlanFinishDateTime = tempProj.PlanFinishDateTime,
                        PlanStartDateTime = tempProj.PlanStartDateTime
                    }; 
                }
                catch (Exception ex)
                {
                    return null;
                }
            }
        }

        [OperationContract]
        public List<Project>  GetProjectList()
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                context.ContextOptions.LazyLoadingEnabled = false;
                try
                {
                    List<Project> projects = new List<Project>();

                    var query = context.Projects.Select(x => x);

                    foreach (Project proj in query)
                    {

                        if (!proj.Tasks.IsLoaded)
                            proj.Tasks.Load();

                        if (!proj.ProjectHasStatus.IsLoaded)
                            proj.ProjectHasStatus.Load();

                            projects.Add(proj);
                    }

                    return projects;

                }
                catch (Exception ex)
                {
                    return null;
                }
            }
        }

        [OperationContract]
        public string AddSystemUser(SystemUser newSystemUser, List<decimal> newSystemUserRoleIDs)
        {
            using (K223DBEntities context = new K223DBEntities())
            {

                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.SystemUsers);
                    context.AddToSystemUsers(new SystemUser
                    {
                        Name = newSystemUser.Name,
                        Surname = newSystemUser.Surname,
                        Patronymic = newSystemUser.Patronymic,
                        E_mail = newSystemUser.E_mail,
                        E_mail2 = newSystemUser.E_mail2,
                        Login = newSystemUser.Login,
                        Password_Hash_ = newSystemUser.Login,
                        MobilePhone = newSystemUser.MobilePhone,
                        WorkPhone = newSystemUser.WorkPhone,
                        IDPosition = newSystemUser.IDPosition,
                        IDDuty = newSystemUser.IDDuty,
                        ProfileStatus = "Active",
                    });
                    context.SaveChanges();
                    foreach (decimal roleID in newSystemUserRoleIDs) newSystemUser.Roles.Add(context.Roles.FirstOrDefault(x => x.IDRole == roleID));
                    context.SaveChanges();
                }
                catch (Exception ex)
                {
                    return String.Format("Ошибка при добавлении пользователя!\n {0}", ex.Message);

                }
            }

            return "Добавление пользователя прошло успешно";
        }

        [OperationContract] // редактирование профиля в БД со сменой ролей
        public bool EditSystemUser(SystemUser userToEdit, List<decimal> editSystemUserRoleIDs)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.SystemUsers);
                    SystemUser tempUser = context.SystemUsers.FirstOrDefault(x => x.IDUser == userToEdit.IDUser);

                    if (tempUser != null)
                    {
                        tempUser.Name = userToEdit.Name;
                        tempUser.Surname = userToEdit.Surname;
                        tempUser.Patronymic = userToEdit.Patronymic;
                        tempUser.E_mail = userToEdit.E_mail;
                        tempUser.E_mail2 = userToEdit.E_mail2;
                        tempUser.Login = userToEdit.Login;
                        tempUser.Password_Hash_ = userToEdit.Password_Hash_;
                        tempUser.MobilePhone = userToEdit.MobilePhone;
                        tempUser.WorkPhone = userToEdit.WorkPhone;
                        tempUser.IDPosition = userToEdit.IDPosition;
                        tempUser.IDDuty = userToEdit.IDDuty;
                        tempUser.ProfileStatus = userToEdit.ProfileStatus;
                        tempUser.Roles.Clear();
                        foreach (decimal roleID in editSystemUserRoleIDs) tempUser.Roles.Add(context.Roles.FirstOrDefault(x => x.IDRole == roleID));
                        context.SaveChanges();
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return true;
        }


        [OperationContract] // редактирование профиля в БД без смены ролей
        public bool EditSystemUserWithoutRoles(SystemUser userToEdit)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.SystemUsers);
                    SystemUser tempUser = context.SystemUsers.FirstOrDefault(x => x.IDUser == userToEdit.IDUser);

                    if (tempUser != null)
                    {
                        tempUser.Name = userToEdit.Name;
                        tempUser.Surname = userToEdit.Surname;
                        tempUser.Patronymic = userToEdit.Patronymic;
                        tempUser.E_mail = userToEdit.E_mail;
                        tempUser.E_mail2 = userToEdit.E_mail2;
                        tempUser.Login = userToEdit.Login;
                        tempUser.Password_Hash_ = userToEdit.Password_Hash_;
                        tempUser.MobilePhone = userToEdit.MobilePhone;
                        tempUser.WorkPhone = userToEdit.WorkPhone;
                        tempUser.IDPosition = userToEdit.IDPosition;
                        tempUser.IDDuty = userToEdit.IDDuty;
                        tempUser.ProfileStatus = userToEdit.ProfileStatus;
                        context.SaveChanges();
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return true;
        }

        [OperationContract]
        public bool RemoveSystemUser(int usID)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.SystemUsers);
                    SystemUser tempUser = context.SystemUsers.FirstOrDefault(x => x.IDUser == usID);
                    if (tempUser != null)
                    {
                        context.DeleteObject(tempUser);
                        context.SaveChanges();
                    }
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return true;
        }

        // получает пользователя по его ID
        [OperationContract]
        public SystemUser GetSystemUserById(int usID)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.SystemUsers);
                    SystemUser tempSystemUser = context.SystemUsers.FirstOrDefault(x => x.IDUser == usID);
                    if (tempSystemUser != null) return tempSystemUser;
                }
                catch (Exception ex)
                {
                }
            }
            return new SystemUser { IDUser = 0 };
        }

        // метод полностью обновляет дерево иерархии в программе на основе БД
        [OperationContract]
        public List<ReportsTo> updateUserTree()
        {
            List<ReportsTo> treeToEdit = new List<ReportsTo>();
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.ReportsToes);
                    foreach (ReportsTo usRep in context.ReportsToes)
                    {
                        treeToEdit.Add(usRep);
                    }
                }
                catch (Exception ex)
                {
                   // return false;
                }
            }
            return treeToEdit;
        }

        // метод загружает фрагмент дерева из БД в программу с юзером, ID которого указан как главный
        [OperationContract]
        public Pair updateUserTreePart(decimal headTreeID)
        {
            bool wasAdding = false;
            bool allUsersAdded = false;
            List<ReportsTo> treeToEdit = new List<ReportsTo>();
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.ReportsToes);
                    ReportsTo tempReportTo = context.ReportsToes.FirstOrDefault(x => x.IDUser == headTreeID);
                    if (tempReportTo != null) treeToEdit.Add(tempReportTo);
                    while (!allUsersAdded) {
                                              wasAdding = false;
                                              foreach (ReportsTo usRep in treeToEdit)
                                              {
                                                 foreach (ReportsTo x in context.ReportsToes) 
                                                     if ((x.IDUserTo == usRep.IDUser) && (!(treeToEdit.Contains(tempReportTo))))
                                                      {
                                                        wasAdding = true;
                                                        treeToEdit.Add(x);
                                                      }
                                              }
                                              if (!wasAdding) allUsersAdded = true;
                                           }
                }
                catch (Exception ex)
                {
                    //return false;
                }
            }
            return new Pair(treeToEdit, wasAdding);
        }

        // метод заменяет фрагменты дерева на новые (переписываются только те которые есть в новом дереве)
        [OperationContract]
        public bool setUserTree(List<ReportsTo> newTree)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.ReportsToes);
                    foreach (ReportsTo usRep in newTree) {
                                                           ReportsTo temp = new ReportsTo();
                                                           while (temp != null)
                                                           {
                                                               context.ReportsToes.FirstOrDefault(x => x.IDUserTo == usRep.IDUser);
                                                               if (temp != null) context.DeleteObject(temp);
                                                           }
                                                         }
                    foreach (ReportsTo usRep in newTree)
                    {
                        ReportsTo temp = new ReportsTo();
                        while (temp != null)
                        {
                            context.ReportsToes.FirstOrDefault(x => x.IDUser == usRep.IDUser);
                            if (temp != null) context.DeleteObject(temp);
                        }
                    }
                    foreach (ReportsTo usRep in newTree)
                    {
                        context.AddToReportsToes(new ReportsTo
                        {
                            IDUser = usRep.IDUser,
                            IDUserTo = usRep.IDUserTo
                        });
                    }
                    context.SaveChanges();
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return true;
        }

        // метод получает список задач пользователя
        [OperationContract]
        public List<decimal> getTasks(int userID)
        {
            List<decimal> tempTaskIDList = new List<decimal>();
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.Executes);
                    foreach (Execute tempExecute in context.Executes)
                        if (tempExecute.IDUser == userID) tempTaskIDList.Add(tempExecute.IDTask);
                }
                catch (Exception ex)
                {
                }
            }
            return tempTaskIDList;
        }


        // метод ставит новый список задач указанному пользователю
        [OperationContract]
        public bool setTasks(decimal usID, List<decimal> userTaskIDs)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.Executes);
                    Execute tempExecute = context.Executes.FirstOrDefault(x => x.IDUser == usID);
                    while (tempExecute != null)
                    {
                        context.Executes.DeleteObject(tempExecute);
                        tempExecute = context.Executes.FirstOrDefault(x => x.IDUser == usID);
                    }

                    foreach (decimal userTaskID in userTaskIDs) context.AddToExecutes(new Execute
                    {
                        IDTask = userTaskID,
                        IDUser = usID
                    });
                    context.SaveChanges();
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return true;
        }

        // получает список ID ролей юзера
        [OperationContract]
        public List<decimal> getUserRolesIDs(decimal userID)
        {
            List<decimal> roleIDs = new List<decimal>();
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.SystemUsers);
                    SystemUser tempSystemUser = context.SystemUsers.FirstOrDefault(x => x.IDUser == userID);
                    if (tempSystemUser != null)
                        foreach (Role tempRole in tempSystemUser.Roles) roleIDs.Add(tempRole.IDRole);
                }
                catch (Exception ex)
                {
                }
            }
            return roleIDs;
        }


        // получает полный список ролей
        [OperationContract]
        public List<Role> getRoles()
        {
            List<Role> roles = new List<Role>();
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.Roles);
                    foreach (Role tempRole in context.Roles) roles.Add(tempRole);
                }
                catch (Exception ex)
                {
                }
            }
            return roles;
        }


        [OperationContract]
        public Task GetTaskById(int id)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.Tasks);
                    Task tempTask = context.Tasks.FirstOrDefault(x => x.IDTask == id);
                    if (tempTask != null)
                    {
                         return tempTask;
                    }

                }
                catch (Exception ex)
                {

                }

            }
            return new Task { IDTask = 0 };
        }




        [OperationContract]
        public List<Role> GetUserRoles(decimal idUser)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    List<Role> minedRoles = new List<Role>();
                     var users = context.SystemUsers;
                     var Query = from user in users
                                 where user.IDUser == idUser
                                 select user.Roles;



                     foreach (var qu in Query)
                     {
                         foreach (Role roleItem in qu)
                             minedRoles.Add(roleItem);
                     }

                     return null;
                    
                }
                catch (Exception ex) { return null; }
            }
        }

        [OperationContract]
        public bool EditTask(Task taskToEdit)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    context.Refresh(RefreshMode.StoreWins, context.Tasks);
                    Task tempTask = context.Tasks.FirstOrDefault(x => x.IDTask == taskToEdit.IDTask);

                    if (tempTask != null)
                    {
                        tempTask.Name = taskToEdit.Name;
                        tempTask.Description = taskToEdit.Description;
                        tempTask.Priority = taskToEdit.Priority;
                        tempTask.Priority = taskToEdit.Priority;
                        tempTask.PlanStartDateTime = taskToEdit.PlanStartDateTime;
                        tempTask.PlanFinishDateTime = taskToEdit.PlanFinishDateTime;
                        tempTask.FactStartDateTime = taskToEdit.FactStartDateTime;
                        tempTask.PlanFinishDateTime = taskToEdit.PlanFinishDateTime;
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return false;
        }

        [OperationContract]
        public bool addToUserDutiesList(bool mode, decimal entityID, decimal userID, TaskProjectStatuses status)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    if (mode)
                    {
                        context.AddToExecutes(new Execute { IDTask = entityID, IDUser = userID });
                        context.TaskHasStatus.AddObject(new TaskHasStatu { IDStatus = (decimal)status, IDTask = entityID });

                    }
                    else
                    {
                        context.AddToLeads(new Lead { IDProject = entityID, IDUser = userID });
                        context.ProjectHasStatus.AddObject(new ProjectHasStatu { IDStatus = (decimal)status, IDProject = entityID });
                        context.SystemUsers.FirstOrDefault().Roles.Add(context.Roles.FirstOrDefault(x => x.IDRole == 1));
                        
                    }

                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return true;
        }

        [OperationContract]
        public bool changeRealWorkTime(bool mode_entity /* true - задача;   false - проект*/, bool mode_timeProperty /* true - время начала, false- время окончания*/,
            decimal entityID, DateTime timeToFix)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    if (mode_entity)
                    {
                        if (mode_timeProperty)
                            context.Tasks.FirstOrDefault(x => (x.IDTask == entityID)).FactStartDateTime = timeToFix;
                        else
                            context.Tasks.FirstOrDefault(x => (x.IDTask == entityID)).FactFinishDateTime = timeToFix;
                    }
                    else
                    {
                        if (mode_timeProperty)
                            context.Projects.FirstOrDefault(x => (x.IDProject == entityID)).FactStartDateTime = timeToFix;
                        else
                            context.Projects.FirstOrDefault(x => (x.IDProject == entityID)).FactFinishDateTime = timeToFix;
                    }

                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return true;
        }


        [OperationContract]
        public bool changeEntityStatus(bool mode_entity /* true - задача;   false - проект*/, decimal entityID, TaskProjectStatuses status)
        {
            using (K223DBEntities context = new K223DBEntities())
            {
                try
                {
                    if (mode_entity)
                        context.TaskHasStatus.FirstOrDefault(x => x.IDTask == entityID).IDStatus = (decimal)status;
                    else
                    {
                        context.ProjectHasStatus.FirstOrDefault(x => x.IDProject == entityID).IDStatus = (decimal)status;
                    }
                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return true;
        }

        //[OperationContract]
        //public void ImportClasses(MainEntities.Priority prio, MainEntities.Project proj, MainEntities.Relations rel, MainEntities.Status stat, MainEntities.Task task,
        //    MainEntities.TaskReferences taskref, MainEntities.User user, MainEntities.UserRelation userrel, MainEntities.UserRoles userrol)
        //{
        //}

    }
}


